package com.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.apache.log4j.Logger;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.ToggleEvent;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.springframework.web.jsf.FacesContextUtils;

import com.builder.FamiliaBuilder;
import com.builder.ProductoBuilder;
import com.builder.ProveedorBuilder;
import com.dao.BaseModelDAO;
import com.model.Deposito;
import com.model.Familia;
import com.model.MovimientoStock;
import com.model.Producto;
import com.model.Proveedor;
import com.model.Stock;
import com.model.Usuario;
import com.query.StockQuery;
import com.util.SpringUtil;
import com.view.FamiliaView;
import com.view.ProductoView;
import com.view.ProveedorView;
import com.view.StockView;

@ManagedBean
@ViewScoped
@SuppressWarnings("serial")
public class StockController extends PaginableController<Stock> {

	private Logger log = Logger.getLogger(StockController.class);
	private BaseModelDAO<Stock> dao;
	private BaseModelDAO<Deposito> daoDeposito;
	private BaseModelDAO<Producto> daoProducto;
	private BaseModelDAO<Familia> daoFamilia;
	private BaseModelDAO<Usuario> daoUsuario;
	private BaseModelDAO<MovimientoStock> daoMovimientoStock;
	private Stock stock;
	Usuario usuario;
	private StockQuery stockQuery;
	private List<Deposito> listaDeposito;
	private List<FamiliaView> listaFamilia;
	private LazyDataModel<MovimientoStock> lazyMovimientosDM;

	private List<ProveedorView> listaDeProveedores;
	private ProveedorView proveedorView;
	private ProductoView producto;

	private BaseModelDAO<Proveedor> daoProveedor;

	@ManagedProperty("#{stockView}")
	private StockView stockView;

	@ManagedProperty("#{proveedorBuilder}")
	private ProveedorBuilder proveedorBuilder;

	@ManagedProperty("#{productoBuilder}")
	private ProductoBuilder productoBuilder;

	@ManagedProperty("#{familiaBuilder}")
	private FamiliaBuilder familiaBuilder;

	@SuppressWarnings("unchecked")
	public StockController() {
		try {
			dao = (BaseModelDAO<Stock>) FacesContextUtils
					.getWebApplicationContext(FacesContext.getCurrentInstance())
					.getBean("stockDAO");

			daoProveedor = (BaseModelDAO<Proveedor>) FacesContextUtils
					.getWebApplicationContext(FacesContext.getCurrentInstance())
					.getBean("proveedorDAO");

			daoDeposito = (BaseModelDAO<Deposito>) FacesContextUtils
					.getWebApplicationContext(FacesContext.getCurrentInstance())
					.getBean("depositoDAO");

			daoProducto = (BaseModelDAO<Producto>) FacesContextUtils
					.getWebApplicationContext(FacesContext.getCurrentInstance())
					.getBean("productoDAO");

			daoMovimientoStock = (BaseModelDAO<MovimientoStock>) FacesContextUtils
					.getWebApplicationContext(FacesContext.getCurrentInstance())
					.getBean("movimientoStockDAO");

			daoUsuario = (BaseModelDAO<Usuario>) FacesContextUtils
					.getWebApplicationContext(FacesContext.getCurrentInstance())
					.getBean("usuarioDAO");

			daoFamilia = (BaseModelDAO<Familia>) FacesContextUtils
					.getWebApplicationContext(FacesContext.getCurrentInstance())
					.getBean("familiaDAO");

			// cargo los depositos que puede ver el usuario
			listaDeposito = daoDeposito.getList(SpringUtil
					.getPrincipalUserName());

			stockQuery = new StockQuery();
			addEdit = false;

			proveedorView = new ProveedorView();

			usuario = daoUsuario.get(SpringUtil.getPrincipalUserName());

		} catch (Throwable e) {
			log.error("Error al inicializar la clase StockController", e);
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_ERROR,
							"Error al realizar la operacion", ""));
		}
	}

	@PostConstruct
	private void init() {
		// se carga el combo de los proveedores
		listaDeProveedores = new ArrayList<ProveedorView>();
		listaDeProveedores.addAll(proveedorBuilder.toView(daoProveedor
				.getList()));
		listaFamilia = familiaBuilder.toView(daoFamilia.getList());
	}

	public void query(ActionEvent event) {
		loadList();
	}

	public void edit(ActionEvent event) {

	}

	public void delete(ActionEvent event) {

	}

	public void add(ActionEvent event) {

	}

	public void save(ActionEvent event) {

	}

	public void cancel(ActionEvent event) {

	}

	public void clear() {
	}

	private void loadList() {

		lazyDM = new LazyDataModel<Stock>() {
			@Override
			public List<Stock> load(int first, int pageSize, String sortField,
					SortOrder sortOrder, Map<String, Object> filters) {

				Map<String, Object> filtro = new HashMap<String, Object>();

				// si es cliente sólo tiene que ver lo suyo
				if (usuario.getCliente() != null
						&& usuario.getCliente().getID() != null) {
					filtro.put("cliente.id", usuario.getCliente().getID());
				}

				filtro.put("deposito.id", stockQuery.getDepositoID());
				filtro.put("producto.id", stockQuery.getProductoID());
				filtro.put("producto.familia.id", stockQuery.getFamiliaID());

				return dao.getList(first, pageSize, "id", true, filtro, true);
			}
		};

		Map<String, Object> filtro = new HashMap<String, Object>();

		// si es cliente sólo tiene que ver lo suyo
		if (usuario.getCliente() != null
				&& usuario.getCliente().getID() != null) {
			filtro.put("cliente.id", usuario.getCliente().getID());
		}

		filtro.put("deposito.id", stockQuery.getDepositoID());
		filtro.put("producto.id", stockQuery.getProductoID());
		filtro.put("producto.familia.id", stockQuery.getFamiliaID());

		lazyDM.setRowCount(dao.count(filtro, true).intValue());
	}

	private void loadListMovimientos() {

		lazyMovimientosDM = new LazyDataModel<MovimientoStock>() {
			@Override
			public List<MovimientoStock> load(int first, int pageSize,
					String sortField, SortOrder sortOrder,
					Map<String, Object> filters) {

				Map<String, Object> filtro = new HashMap<String, Object>();
				filtro.put("stock.id", lazyDM.getRowData().getID());

				return daoMovimientoStock.getList(first, pageSize, "fecha",
						true, filtro, true);
			}
		};

		Map<String, Object> filtro = new HashMap<String, Object>();
		filtro.put("stock.id", lazyDM.getRowData().getID());
		lazyMovimientosDM.setRowCount(daoMovimientoStock.count(filtro, true)
				.intValue());
	}

	public void onRowToggle(ToggleEvent event) {
		loadListMovimientos();
	}

	public List<ProductoView> completeProducto(String query) {
		List<ProductoView> listaProducto = null;
		try {

			List<Producto> listaProductosEntity = daoProducto.getList(query);
			if (listaProductosEntity != null && listaProductosEntity.size() > 0) {
				listaProducto = productoBuilder.toView(listaProductosEntity);
			}

		} catch (Throwable e) {
			log.error("Error en le metodo completeProducto: ", e);
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_ERROR,
							"Error al realizar la operacion", ""));
		}
		return listaProducto;
	}

	public boolean isProductoSelected() {
		return (producto != null && producto.getId() != null);
	}

	public void deselecionarProducto(ActionEvent event) {
		producto = null;
		stockQuery.setProductoID(null);
	}

	public void productoSelectChange(SelectEvent event) {
		producto = (ProductoView) event.getObject();

		if (producto != null) {
			stockQuery.setProductoID(producto.getId());
		}

		System.out
				.println("se eligio una un producto " + producto.getDetalle());
	}

	public Logger getLog() {
		return log;
	}

	public void setLog(Logger log) {
		this.log = log;
	}

	public BaseModelDAO<Stock> getDao() {
		return dao;
	}

	public void setDao(BaseModelDAO<Stock> dao) {
		this.dao = dao;
	}

	public Stock getStock() {
		return stock;
	}

	public void setStock(Stock stock) {
		this.stock = stock;
	}

	public StockQuery getStockQuery() {
		return stockQuery;
	}

	public void setStockQuery(StockQuery stockQuery) {
		this.stockQuery = stockQuery;
	}

	public List<ProveedorView> getListaDeProveedores() {
		return listaDeProveedores;
	}

	public void setListaDeProveedores(List<ProveedorView> listaDeProveedores) {
		this.listaDeProveedores = listaDeProveedores;
	}

	public BaseModelDAO<Proveedor> getDaoProveedor() {
		return daoProveedor;
	}

	public void setDaoProveedor(BaseModelDAO<Proveedor> daoProveedor) {
		this.daoProveedor = daoProveedor;
	}

	public StockView getStockView() {
		return stockView;
	}

	public void setStockView(StockView stockView) {
		this.stockView = stockView;
	}

	public ProveedorView getProveedorView() {
		return proveedorView;
	}

	public void setProveedorView(ProveedorView proveedorView) {
		this.proveedorView = proveedorView;
	}

	public ProveedorBuilder getProveedorBuilder() {
		return proveedorBuilder;
	}

	public void setProveedorBuilder(ProveedorBuilder proveedorBuilder) {
		this.proveedorBuilder = proveedorBuilder;
	}

	public List<Deposito> getListaDeposito() {
		return listaDeposito;
	}

	public ProductoView getProducto() {
		return producto;
	}

	public void setProducto(ProductoView producto) {
		this.producto = producto;
	}

	public ProductoBuilder getProductoBuilder() {
		return productoBuilder;
	}

	public void setProductoBuilder(ProductoBuilder productoBuilder) {
		this.productoBuilder = productoBuilder;
	}

	public LazyDataModel<MovimientoStock> getLazyMovimientosDM() {
		return lazyMovimientosDM;
	}

	public FamiliaBuilder getFamiliaBuilder() {
		return familiaBuilder;
	}

	public void setFamiliaBuilder(FamiliaBuilder familiaBuilder) {
		this.familiaBuilder = familiaBuilder;
	}

	public List<FamiliaView> getListaFamilia() {
		return listaFamilia;
	}

}
